package com.aaa.aspect;

import com.alibaba.fastjson.JSONObject;
import com.aaa.annotation.SysLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

@Aspect
@Component
public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(LogAspect.class);

    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定义切入点，切入点为com.aaa.common.annotation.SysLog下的所有函数
     */
    @Pointcut("@annotation(com.aaa.annotation.SysLog)")
    public void webLog(){}

    /**
     * 前置通知：在连接点之前执行的通知
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());  // 这个东西注了 进不去
        // 接收到请求，记录请求内容
        System.out.println("接收到请求，记录请求内容-------------------------");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 获得Session
        HttpSession session = (HttpSession) attributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        // 记录下请求内容
        logger.info("classMethod:======>" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("method:======>" + request.getMethod());  // 获得请求登录的方式
        //获取传入目标方法的参数


        if(session != null){
            logger.info("session id :======>" + session.getId());  // 获得session的id
        }
      // 获取方法的关键信息，类，包
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();  // 获取方法上的注解
        SysLog mylog = method.getAnnotation(com.aaa.annotation.SysLog.class);
        // 获取  LonginController 上的注解
        if(mylog != null){
            System.out.println("获取注解上的描述");
            //注解上的描述
            logger.info("mylog:======>" + mylog.value());
        }
    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        try {
            String name = proceedingJoinPoint.getSignature().getName();
            System.out.println("环绕前，执行"+name+"方法");
            Object obj = proceedingJoinPoint.proceed();
            System.out.println("环绕后，执行"+name+"方法");
            return obj;
        } catch (Exception e) {
            logger.error("exception message :======>" + e.getMessage());
            throw e;
        }
    }

    /**
     * 返回通知：在目标方法成功执行之后调用通知
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
        System.out.println("目标方法成功执行之后的通知-------------------");

        // 判断成功返回true 跳转的页面
        String retString = JSONObject.toJSONString(ret);
        retString = retString.length() > 2000 ? retString.substring(2000) : retString;
        logger.info("ret:======>" + retString);

        // 用户登录的时间
        logger.info("useTime:======>" + (System.currentTimeMillis() - startTime.get()) + "");
    }
}
